/**
 * 
 */
package pruebas.tiendaOl.dominio.servicio;

import iades.fabricaciones.InterceptorTransaccional.TransaccionUnidaAUnidadTrabajo;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
import javax.enterprise.inject.Any;
import javax.inject.Inject;

import pruebas.tiendaOl.dominio.casosUso.CasosUsoCliente;
import pruebas.tiendaOl.dominio.entidades.Carrito.EventoCarrito;
import pruebas.tiendaOl.dominio.entidades.TipoArticulo;
import pruebas.tiendaOl.dominio.incrustables.ItemCarrito;
import pruebas.tiendaOl.ipsWeb.IpsCarrito;

import com.intelap.incrustables.Dinero;
import com.intelap.utils.ProductorRecursos;

/** Proveedor del servicio: acceso al carrito
 * Nota: Se usó {@link ConversationScoped} en lugar de {@link Dependent} (que sería mas apropiado porque no existiria la exigencia de tener el mismo context scope que el cliente para no perder o duplicar observadores), para que sea el observador de eventos de la instancia asociada al cliente el que reciba los eventos en lugar de la instancia que crearía CDI si fuera {@link Dependent}.
 * @author Gustavo */
@Dependent
public class PsCarrito implements IpsCarrito {
	@Inject
	private CasosUsoCliente casosUsoCliente;

	@Override
	@TransaccionUnidaAUnidadTrabajo
	public List<IpsItemCarrito> getItems() {
		List<IpsItemCarrito> items = new ArrayList<>(casosUsoCliente.getCarrito().getItems_const().size());
		for (final Map.Entry<TipoArticulo, ItemCarrito> entry : casosUsoCliente.getCarrito().getItems_const().entrySet()) {
			items.add(new IpsItemCarritoImpl(entry.getKey(), entry.getValue()));
		}
		return items;
	}

	@Override
	public void sacarArticulosDeCarrito(IpsItemCarrito item, int cantidad) {
		casosUsoCliente.sacarArticulosDeCarrito(((IpsItemCarritoImpl) item).tipoArticulo, cantidad); // usar esta linea cuando el {@link SustentadorUnidadTrabajo} es SessionScoped
//		casosUsoCliente.sacarArticulosDeCarrito(ut.getInstanciaAtada(((IpsItemCarritoImpl) item).tipoArticulo), cantidad); // usar esta linea cuando el {@link SustentadorUnidadTrabajo} es RequestScoped
	}

	@Override
	public String getId() {
		return Integer.toString(System.identityHashCode(this));
	}

	//// Adaptacion de eventos del dominio a como los requiere la presentacion ////

	@Inject
	private Event<EventoCambiosCarrito> lanzadorEventoCambiosCarrito;
	void cuandoEventoCarritoItemAgregado(@Observes(during = TransactionPhase.AFTER_SUCCESS) @Any final EventoCarrito evento) {
		logger.info("PsCarrito#" + System.identityHashCode(this) + ": anunciando " + evento);
		lanzadorEventoCambiosCarrito.fire(new EventoCambiosCarrito() {
			@Override
			public String getNombreArticulo() {
				return evento.tipoArticulo.getNombre();
			}
			@Override
			public int getCantidadAgregada() {
				return evento.cantidadAgregada;
			}
		});
	}


	///// adaptadores de objetos del dominio a como los requiere la presentacion ////

	private static class IpsItemCarritoImpl implements IpsItemCarrito {
		final TipoArticulo tipoArticulo;
		final ItemCarrito itemCarrito;

		IpsItemCarritoImpl(TipoArticulo tipoArticulo, ItemCarrito itemCarrito) {
			this.tipoArticulo = tipoArticulo;
			this.itemCarrito = itemCarrito;
		}

		@Override
		public String getNombre() {
			return tipoArticulo.getNombre();
		}
		@Override
		public Dinero getPrecio() {
			return tipoArticulo.getPrecio();
		}
		@Override
		public int getCantidad() {
			return itemCarrito.getCantidad();
		}
	}

	//// Debug ////
	private static Logger logger = ProductorRecursos.getLogger(PsCarrito.class);
	@PostConstruct
	void postConstruct() {
		logger.info("postConstruct de PsCarrito#" + System.identityHashCode(this));
	}
	@PreDestroy
	void preDestroy() {
		logger.info("preDestroy de PsCarrito#" + System.identityHashCode(this));
	}
}
